# -*- coding: utf-8 -*-

"""
Module implementing Form.
"""

from PyQt5.QtCore import pyqtSlot
from ..proxy_menu import ProxyMenu
from PyQt5.QtWidgets import QWidget

from .Ui_ip_online import Ui_Form
# import PyQt5.QtCore as PQC
from PyQt5.QtCore import pyqtSignal, Qt, pyqtSlot, QTimer, QProcess
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (QApplication, QMenu, QStatusBar, QLabel)
from log import logger

from project import IpState
from project.SetPcIp.mainConfigPcIp import UI_pc_ip
from project.ipOnline.proxy_network import ProxyNetWorkCard
from project.ipOnline.proxylist_widget import ProxyListWidget
from project.ipOnline import config_ip_online, f_handle_config_dump
from ..pack.ping_ip import ManageTheads
from ..pack.standard_model import CollectModel
from .import ___xx__mtab
from functools import partial


# class Flush:
#     def __init__(self, model: ContainerInListModel):
#         self.model = model
#
#         pass
#
#     def flush(self):
#         self.model.flush()
    
    
    

class Form(QWidget, Ui_Form):

    _startThread = pyqtSignal()

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super(Form, self).__init__(parent)
        self.setupUi(self)
        self.resize(1426, 750)
    
        # self.init_statusBar()
        self.init_tabWidget()
        self.init_tab1()
        self.init_tab2()
    
        
    def init_tabWidget(self):
        # self.tabWidget
        self.tabWidget.setCurrentIndex(0)
        self.tabWidget.tabBar().setFont(QFont("宋体", 12))
        # self.tabWidget.tabBar().setMinimumHeight(90)
        # self.tabWidget.setTabText(2, "")
        self.pcip_widget = UI_pc_ip()
        self.tabWidget.addTab(self.pcip_widget, "设置本机IP")
        pass
    
     
     
    def init_statusBar_tab1(self):
        """
       nihao
       nu
        
        """
        self.stateBar = QStatusBar(self)
        self.stateBar.setMaximumHeight(20)
        
        label = QLabel(self)
        label.setText("nihao")
        
        self.stateBar.addPermanentWidget(label, stretch=4)
        self.stateBar.addPermanentWidget(self.progressBar, stretch=2)
        self.verticalLayout_global.addWidget(self.stateBar)
        self.verticalLayout_global.setSpacing(0)
        
        
    def init_tab1(self):
        """
        初始化控件
        
        """
        logger.debug("init_tab1")
        
        self.set_line_btn_hide(True)
        
        self.progressBar.setValue(0)
        
        # todo del this button
        self.push_test.hide()
        
       # data
        self.manage_threads = ManageTheads()
        self.manage_threads.manage_signal_finishedall.connect(self.slot_finished_all_thread)
        self.manage_threads.manage_signal_send_onlineip.connect(self.slot_receive_ip)
        self.manage_threads.manage_signal_oneth_end[int].connect(self.progressBar.setValue)

        
        # 设置表格
        # model
        # self.model = ContainerInListModel()
        self.model = CollectModel()
        self.tableview.setColumnWidth(0, 50)
        self.tableview.setModel(self.model)
        # mtab.set_header(self.model)
        
        
        #
        self.proxy_network = ProxyNetWorkCard()
        card = self.proxy_network.card
        
        #
        self.proxy_list_widget = ProxyListWidget(self.sectionListWidget, self)
        self.proxy_list_widget.create_items_from_card(card)
        self.proxy_list_widget.btnClickSignal[str].connect(self.__on_checkip_range)
        # init sectionListWidgeto
        
        # card combo
        self.comboBox.addItems(self.proxy_network.get_cardname_list())
        
   
    def init_tab2(self):
    
        logger.debug("init_tab2")
        #
        self.lineLineIp.setText("192.168.10.100")
        # self.lineLineIpEnd.setText("192.168.10.106")
        self.lineLineIp.setPlaceholderText("192.168.10.100")
        self.lineLineIpEnd.setPlaceholderText("192.168.10.106")
        
        self.init_tableview_sustain_tab2()
        # timer
        self.timer = QTimer()
        self.timer.timeout.connect(self.slot_timer)
        
    
    def slot_timer(self):
        logger.info("正在运行的线程个数: {}". format(self.modelSustain.mpt.runing_count()))
        self.modelSustain.flush()
        
    def init_tableview_sustain_tab2(self):
        """
        初始化另外一个表格
        持续检测IP的在线状态
        """
        
        logger.debug("init_tableview_sustain_tab2")

        self.tableViewSustain.resize(1000, 600)
        self.tableViewSustain.setColumnWidth(0, 62)
        # 右键菜单
        self.tableViewSustain.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tableViewSustain.customContextMenuRequested.connect(self.generateMenu)
        
        self.modelSustain = CollectModel()
        self.tableViewSustain.setModel(self.modelSustain)
        
        # datas
        
        #向sustain表格插入默认的值
        
        ipate_list = config_ip_online.get_IpSate_obj_from_dict()
        if ipate_list is not None:
            for ipo in ipate_list:
                self.modelSustain.ctd.add_ip(ipo)
        self.modelSustain.flush()

        
    
                
    
    def generateMenu(self, pos):
        
        def change_ipo_checken(ipstr: str, enable:bool):
            sec = IpState(ipstr).section()
            struct = self.modelSustain.ctd._get_struct_from_section(sec)
            ipo = struct.get_ipo(ipstr)
            if enable: ipo.set_unknow()
            else: ipo.set_invalid()
            
            self.modelSustain.flush()
            
        def change_ipos_checken(sec: str, enable: bool):
            struct = self.modelSustain.ctd._get_struct_from_section(sec)
            for ipo in struct:
                if enable: ipo.set_unknow()
                else: ipo.set_invalid()
            self.modelSustain.flush()

        def del_ipo(ipstr: str):
            ipo = self.modelSustain.ctd.remove_ipo(ipstr)
            self.modelSustain.mpt.pop(ipo)
            self.modelSustain.flush()

        def del_ipos_section(section: str):
            ipos = self.modelSustain.ctd.remove_struct_from_section(section)
            for ipo in ipos:
                self.modelSustain.mpt.pop(ipo)
            self.modelSustain.flush()

        if self.focusWidget() == self.tableViewSustain:
            proxymenu = ProxyMenu()
            index = self.tableViewSustain.currentIndex()
            ipstr_cur = self.modelSustain.data((index))
            try:
                section = IpState(ipstr_cur).section()
            except TypeError:
                return
        
            f_close_one = partial(change_ipo_checken, ipstr_cur, False)
            f_open_one = partial(change_ipo_checken, ipstr_cur, True)
            f_close_section = partial(change_ipos_checken, section , False)
            f_open_section = partial(change_ipos_checken, section, True)
            f_del_one = partial(del_ipo, ipstr_cur)
            f_del_section = partial(del_ipos_section, section)
            
            proxymenu.add( "禁止{}检测".format(ipstr_cur), f_close_one )
            proxymenu.add( "允许{}检测".format(ipstr_cur), f_open_one )
            proxymenu.add_separator()
            proxymenu.add( "禁止{}网段的IP检测".format(section), f_close_section )
            proxymenu.add( "允许{}网段的IP检测".format(section), f_open_section )
            proxymenu.add_separator()
            proxymenu.add( "删除 {}".format(ipstr_cur), f_del_one )
            proxymenu.add( "删除{}网段的IP检测".format(section), f_del_section )
            
            proxymenu.exec(self.tableViewSustain, pos)
        
        

        
            
    
    @pyqtSlot()
    def on_push_test_clicked(self):
        """
        测试按扭
        """
        # todo delte button and this slot function
        pass
    
    @pyqtSlot()
    def on_btn_clear_clicked(self):
        """
        清空表格
        """
        self.model.clear()
        self.model.flush()
        
        pass
    
    # -------------------------------------------------------------
    # 结束
    # -------------------------------------------------------------
    
    # def _set_current_section(self, ip):
    #     sec = IpState(ip).section()
    #     self.model.switch_section(sec)
    
    
    def slot_receive_ip(self, ip):
        """
        singal信号的槽
        作用:设置一个在线IP 所对应的IP的 背景颜色
        """
        logger.debug("success ping : {}".format(ip))
        # self.model.add_ip_update_all_model(ip)
        ipo = IpState(ip)
        ipo.set_new()
        self.model.ctd.add_ip(ipo)
        self.model.flush()
    
    
    def __on_checkip_range(self, section: str):
        
        logger.debug("click list btns of < {} btn>".format(section))
        self.model.ctd.starting_add(section)
        self.model.flush()
        
        self.progressBar.setValue(0)
        
        self.manage_threads.set_ips(section)
        self.manage_threads.create_threads()
        self.manage_threads.start()
    
    def slot_finished_all_thread(self):
        """
        所有的ip ping完毕
        """
        print("收到信号,执行槽 finished_all_ths")
        # 结束所有的th
        self.manage_threads.quit()
        self.progressBar.setValue(100)
        
        # no on line
        # self.model.update_not_online()
        self.model.ctd.ending_add()
        self.model.flush()
        # 设置ListWidget里面的btn的enable状态
        self.proxy_list_widget.set_btn_status(True)
    
    @pyqtSlot()
    def on_btnAddSection_clicked(self):
        """
        添加电脑当前网卡的网段
        """
        logger.info("开始添加一个PC当前网卡的网段")
        self.set_line_btn_hide(False)
    
    @pyqtSlot()
    def on_btnSectionAddSure_clicked(self):
        """
        确定添加输入的网段
        """
        section_: str = self.lineSection.text()
        if not section_.isalnum():
            # 如果字符串不是数字,就返回
            logger.warning("输入的网段不是数字")
            return
        
        PC_TAIL = '151'
        ip_tsr = "192.168.{}.{}".format(section_, PC_TAIL)
        
        # 本机添加一个IP段
        rev = self.proxy_network.add_and_set_pc_ip(ip_tsr)
        if rev is None:
            # 设置本机不成功
            self.lineSection.setText("")
            self.set_line_btn_hide(True)
            logger.warning("添加本要IP不成功~")
            return
        
        # QListWidget列表添加一行
        self.proxy_list_widget.add_section(ip_tsr)
        self.set_line_btn_hide(True)
        logger.info("添加PC 当前网卡的一个网段成功")
    
    @pyqtSlot(str)
    def on_comboBox_currentIndexChanged(self, p0):
        """
        切换当前的网卡
        @param p0 DESCRIPTION
        @type str
        """
        
        card_name = p0
        self.proxy_network.switch_current_card(card_name)
        
        card = self.proxy_network.card
        self.proxy_list_widget.create_items_from_card(card)
    

    @pyqtSlot()
    def on_btnSustainStart_clicked(self):
        """
        Slot documentation goes here.
        """
        logger.debug("开始持续的ping所有的有效IP...")
        # self.mthreadSustain = ManageTheadSustain()
        
        ipos = self.modelSustain.ctd.ipos
        self.modelSustain.mpt.create_many_ths(ipos)
        self.modelSustain.mpt.start()
        
        self.timer.start(1000)
        
        self.btnSustainStart.setEnabled(False)
    
    @pyqtSlot()
    def on_btnSustainStop_clicked(self):
        """
        Slot documentation goes here.
        """
        logger.debug("所在持续ping IP线程停止")
        # self.mthreadSustain.quit()
        self.timer.stop()
        
        self.modelSustain.mpt.quit()

        self.btnSustainStart.setEnabled(True)
        self.modelSustain.flush()
        


    def set_line_btn_hide(self, b_status):
        
        b_status = bool(b_status)
        self.lineSection.setHidden(b_status)
        self.btnSectionAddSure.setHidden(b_status)
    
    
    def closeEvent(self, a0) -> None:
        print('closeEvent')
        
        if self.modelSustain.mpt.runing_count() > 0:
            self.modelSustain.mpt.quit()
        
        # 保存数据到配置
        config_ip_online.set_dict_from_IPState_Obj(
            self.modelSustain.ctd.ipos
        )
        f_handle_config_dump()
        
    
    @pyqtSlot()
    def on_btnFlushIp_clicked(self):
        """
        添加新的字段后,手动刷新列表
        """
        
    @pyqtSlot()
    def on_btnAddSustain_clicked(self):
        """
        添加IP到持续检测表格
        todo 需要重构 function
        """
        logger.debug("QPushButton: AddSustain 添加IP到持续检测表格")
        start = self.lineLineIp.text()
        end = self.lineLineIpEnd.text()
        logger.debug("QLineEdit start ip is :{}, end ip is {}".format(start, end))
        ipos = IpState.get_range_ipos(start, end)
        if ipos is None: return
        
        is_th_runing = True if self.modelSustain.mpt.runing_count()  > 0 else False
        for ipo in ipos:
            self.modelSustain.ctd.add_ip(ipo)
            if is_th_runing:
                th = self.modelSustain.mpt.create_one(ipo)
                th.start()
            
        self.modelSustain.flush()
        
        
        
        
def restart_real_live(qApp):
    """
    重启程序
    """
    qApp.quit()
    p = QProcess
    p.startDetached(qApp.applicationFilePath())


def main():
    # PyQt / Qt解决分辨率不同的设备显示问题
    # QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
    import sys
    app = QApplication(sys.argv)
    win = Form()
    win.push_test.hide()
    win.show()
    sys.exit(app.exec_())